﻿namespace CloudBlitz.DeploymentManager.DeploymentOperations
{
    using System;
    using System.Linq;
    using System.Threading;

    using AzureManagement.AzureDataContracts;

    using CloudBlitz.DeploymentManager.DeploymentWorkflow;

    public class WaitForDeploymentToStabilizeOperation : DeploymentOperationBase
    {
        private readonly IAzureServiceClientsFactory azureServiceClientsFactory;
        private readonly TimeSpan timeout;

        public WaitForDeploymentToStabilizeOperation(IAzureServiceClientsFactory azureServiceClientsFactory, TimeSpan timeout) : base(5)
        {
            this.azureServiceClientsFactory = azureServiceClientsFactory;
            this.timeout = timeout;
        }

        protected override OperationResult ExecuteOverride(DeploymentContext context)
        {
            var azureServiceManagementClient = this.azureServiceClientsFactory.CreateServiceManagementClient(context.AzureCredentials);

            var stabilized = false;

            var start = DateTime.Now;

            this.RaiseProgressChangedEvent(0, "Waiting for deployment to stabilize");
            do
            {
                var deployment = azureServiceManagementClient.GetDeployment(context.HostedServiceName, DeploymentSlots.Production).Result;
                if (deployment.Status == DeploymentStatuses.Running)
                {
                    stabilized = deployment.RoleInstanceList.All(roleInstance => roleInstance.InstanceStatus == InstanceStatuses.ReadyRole);
                }

                Thread.Sleep(TimeSpan.FromSeconds(20));

                if (DateTime.Now.Subtract(start) >= this.timeout)
                {
                    return new OperationResult(DeploymentOperationStatus.Failed, "Deployment startup timeout exceeded.");
                }
            }
            while (!stabilized);

            this.RaiseProgressChangedEvent(100, "Deployment stabilized");
            return OperationResult.Success;
        }
    }
}